import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { createHash } from "node:crypto";
import { firstValueFrom } from 'rxjs';
import { HttpService } from '@nestjs/axios';
import { LoggerService } from '@/common/logger/logger.service';
import { RedisKeyEnum } from '@/common/enums/redis-key.enum';
import { handleError } from '@/utils/handle.error';
import { RedisService } from '@/common/redis/redis.service';

@Injectable()
export class WeComService {


  constructor(
    private readonly httpService: HttpService,
    private readonly logger: LoggerService,
    private readonly redisService: RedisService,
  ) {
    this.logger.setContext(WeComService.name);
  }

  /** 获取企业微信jsapi的ticket */
  async getAccessToken(query) {
    try {
      const { corpid, corpsecret } = query
      // const key = `${RedisKeyEnum.WeComKey}${corpid}/${corpsecret}`
      // const cache = await this.redisService._get(key).catch((err) => { });
      // if (cache) {
      //   return cache
      // }
      const res = await firstValueFrom(
        this.httpService.get(`https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${corpid}&corpsecret=${corpsecret}`)
      )
      if (res.data.errcode !== 0) {
        throw new HttpException("获取失败", HttpStatus.OK);
      }
      // this.redisService._setex(key, res.data.expires_in - 10000, res.data.access_token)
      return res.data.access_token
    } catch (error) {
      handleError(this.logger, error, {
        common: "获取企业微信Access Token失败",
      });
    }
  }


  /** 获取企业微信agent_config的 jsapi的ticket 用于接口权限 */
  async getAgentConfigTicket(accessToken: string) {
    try {
      const res = await firstValueFrom(
        this.httpService.get(`https://qyapi.weixin.qq.com/cgi-bin/ticket/get?access_token=${accessToken}&type=agent_config`)
      )
      return res.data.ticket
    } catch (error) {
      handleError(this.logger, error, {
        common: "获取企业微信agent_config的ticket失败",
      });
    }
  }

  /** 获取企业微信config的ticket 用于config */
  async getConfigTicket(accessToken: string) {
    try {
      const res = await firstValueFrom(
        this.httpService.get(`https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token=${accessToken}`)
      )
      return res.data.ticket
    } catch (error) {
      handleError(this.logger, error, {
        common: "获取企业微信config的ticket失败",
      });
    }
  }



  /**
   * 生成微信JS-SDK签名
   * @param jsapi_ticket 微信JSAPI Ticket
   * @param url 当前网页URL（不包含#及其后面部分）
   * @returns 返回签名所需的所有参数
   */
  async generateQWSignature(query) {

    const { url, type, corpid, corpsecret } = query
    const token = await this.getAccessToken({ corpid, corpsecret })
    // 0. 获取jsapi_ticket
    const ticket = type === 'config' ? await this.getConfigTicket(token) : await this.getAgentConfigTicket(token)

    // 1. 生成随机字符串（16位）
    const noncestr = this.generateNonceStr();

    // 2. 生成时间戳（秒级）
    const timestamp = Math.floor(Date.now() / 1000);

    // 3. 按固定顺序拼接字符串
    const string1 = `jsapi_ticket=${ticket}&noncestr=${noncestr}&timestamp=${timestamp}&url=${url}`;

    // 4. 生成SHA1签名
    const signature = createHash('sha1')
      .update(string1)
      .digest('hex');

    return {
      noncestr,
      timestamp,
      url,
      signature,
    };
  }

  /**
   * 生成随机字符串
   * @param length 字符串长度，默认16
   * @returns 随机字符串
   */
  private generateNonceStr(length = 16): string {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';
    for (let i = 0; i < length; i++) {
      result += chars.charAt(Math.floor(Math.random() * chars.length));
    }
    return result;
  }

}
